package com.ruoyi.equip.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.github.yitter.idgen.YitIdHelper;
import com.ruoyi.common.core.domain.SelectEntity;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.equip.domain.TagData;
import com.ruoyi.equip.domain.TagInfo;
import com.ruoyi.equip.domain.entity.table.ExportParam;
import com.ruoyi.equip.domain.entity.table.TagTableEntity;
import com.ruoyi.equip.domain.vo.TagVo;
import com.ruoyi.equip.mapper.DeviceInfoMapper;
import com.ruoyi.equip.mapper.TagDataMapper;
import com.ruoyi.equip.mapper.TagInfoMapper;
import com.ruoyi.equip.service.ITagInfoService;
import com.ruoyi.equip.service.IThingModelService;
import com.ruoyi.equip.util.HeartCacheUtils;
import com.ruoyi.equip.vert.parser.DataReader;
import com.ruoyi.equip.vert.service.impl.DataTransfer;
import com.ruoyi.equip.vert.service.impl.ReqTagNumTransfer;
import com.ruoyi.td.entity.DevicePropertyCache;
import com.ruoyi.td.entity.DevicePropertyLogQueryBo;
import com.ruoyi.td.service.IDeviceInfoData;
import com.ruoyi.td.vo.ThingModelVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

import static com.ruoyi.equip.util.CacheUtils.*;
import static com.ruoyi.equip.vert.TcpReaderConstant.*;

/**
 * 网关业务处理逻辑层
 */
@Service
@Slf4j
public class TagInfoServiceImpl implements ITagInfoService
{

    @Resource
    IThingModelService thingModelService;
    @Resource
    private TagInfoMapper tagInfoMapper;

    @Resource
    private IDeviceInfoData deviceInfoData;


    @Resource
    DeviceInfoMapper deviceInfoMapper;

    @Resource
    TagDataMapper tagDataMapper;


    /**
     * 标签类型Map
     */
    private static final Map<Integer, String> TAG_TYPE_MAP = Map.of(
            0, "温度",
            1, "压力",
            2, "温湿度"
    );

    /**
     * 查询所有标签
     *
     * @param tagVo
     */
    @Override
    public List<TagVo> selectTagInfoList(TagVo tagVo)
    {
        List<TagVo> tagVos = tagInfoMapper.selectTagInfoList(tagVo);
        tagVos.forEach(tagVo1 ->
        {
            tagVo1.setOnline(HeartCacheUtils.isOnline(tagVo1.getId()));
        });
        return tagVos;
    }

    @Override
    public List<TagVo> realData(TagVo tagVo)
    {
        List<TagVo> tagVos = selectTagInfoList(tagVo);
        tagVos.forEach(tagVo1 ->
        {
            //Map<String, DevicePropertyCache> properties = deviceInfoData.getProperties(tagVo1.getId());
            Map<String, DevicePropertyCache> map = DataTransfer.realData.get(tagVo1.getId());
            if (map == null) {
                map = new HashMap<>();
                TagData tagData = tagDataMapper.selectLast(tagVo1.getId());
                DevicePropertyCache devicePropertyCache = new DevicePropertyCache();
                if (tagData == null) {
                    devicePropertyCache = new DevicePropertyCache("温度", "℃", null, null);

                } else {
                    devicePropertyCache = new DevicePropertyCache("温度", "℃", tagData.getData(), tagData.getReportTime());

                }
                map.put("tempature", devicePropertyCache);
                DataTransfer.realData.put(tagVo1.getId(), map);
            }
            tagVo1.setProperty(map);
        });
        return tagVos;
    }

    /**
     * 新增标签
     */
    @Override
    @Transactional
    public int add(TagVo tagVo)
    {
        tagVo.setId(YitIdHelper.nextId() + "");
        int rows = tagInfoMapper.insert(tagVo);
        // 增加属性缓存
        if (StringUtils.isNotEmpty(tagVo.getParentId())) {
            String deviceSbId = deviceInfoMapper.selectSbId(tagVo.getParentId());
            updateTagInfo(deviceSbId, tagVo);
            // 发起新增标签
            sendOptTagMsg(deviceSbId, tagVo, TAG_OPT_ADD);
        }
        return rows;
    }

    public void sendOptTagMsg(String readerId, TagInfo tagVo, String tagOpt)
    {
        String handlerId = DataReader.readHandleMap.get(readerId);
        ReqTagNumTransfer transfer = SpringUtils.getBean(ReqTagNumTransfer.class);
        transfer.sendOptTagMsg(handlerId, readerId, tagVo.getSbId(), tagVo.getAnt(), tagVo.getType(), tagOpt);
    }

    /**
     * 修改指定标签
     */
    @Override
    @Transactional
    public int update(TagVo tagVo)
    {
        // 查询原来父ID
        String oldParentId = tagInfoMapper.selectOldParentId(tagVo.getId());
        int i = tagInfoMapper.updateById(tagVo);
        String oldDeviceSbId = deviceInfoMapper.selectSbId(oldParentId);
        String newDeviceSbId = deviceInfoMapper.selectSbId(tagVo.getParentId());


        if (StringUtils.isNotNull(oldDeviceSbId)) {
            sendOptTagMsg(oldDeviceSbId, tagVo, TAG_OPT_DEL);
        }

        if (StringUtils.isNotNull(newDeviceSbId)) {
            sendOptTagMsg(newDeviceSbId, tagVo, TAG_OPT_ADD);
        }
        updateTagInfo(oldDeviceSbId, newDeviceSbId, tagVo);
        return i;
    }

    /**
     * 删除指定标签
     *
     * @param tagId 标签物理ID
     */
    @Override
    @Transactional
    public int deleteById(String tagId)
    {
        TagInfo tagInfo = tagInfoMapper.selectById(tagId);
        int i = tagInfoMapper.deleteById(tagId);
        String deviceSbId = deviceInfoMapper.selectSbId(tagInfo.getParentId());
        removeTagInfo(deviceSbId, tagInfo.getSbId());
        sendOptTagMsg(deviceSbId, tagInfo, TAG_OPT_DEL);
        //clearCacheData(tagInfo.getSbId());
        return i;
    }

    /**
     * 批量删除标签
     *
     * @param tagIds 标签物理ID
     */
    @Override
    @Transactional
    public void batchDelTag(List<String> tagIds)
    {
        tagIds.forEach(this::deleteById);
    }

    /**
     * 获取指定标签详情
     *
     * @param tagId 标签物理ID
     */
    @Override
    public TagVo getTagsDetail(String tagId)
    {
        TagVo tagVo = tagInfoMapper.selectDetail(tagId);
        tagVo.setProperty(deviceInfoData.getProperties(tagId));
        return tagVo;
    }

    /**
     * 标签导出
     */
    @Override
    public void export(HttpServletResponse response, ExportParam exportParam)
    {
        if (SecurityUtils.hasRole("usergroup")) {
            exportParam.setDeptId(String.valueOf(SecurityUtils.getDeptId()));
        } else if (SecurityUtils.hasRole("emp")) {
            exportParam.setUserId(String.valueOf(SecurityUtils.getUserId()));
        }
        List<TagTableEntity> list = tagInfoMapper.selectExportData(exportParam);
        list.forEach(item -> item.setTypeName(TAG_TYPE_MAP.get(item.getType())));
        ExcelUtil<TagTableEntity> util = new ExcelUtil<TagTableEntity>(TagTableEntity.class);
        util.exportExcel(response, list, "标签数据");
    }

    /**
     * 获取指定读写器下所有标签
     *
     * @param parentId 读写器物理ID
     */
    @Override
    public List<TagVo> getByParentId(String parentId)
    {
        return tagInfoMapper.selectListByParentId(parentId);
    }

    /**
     * 解绑指定标签
     *
     * @param tagId 标签物理ID
     */
    @Override
    @Transactional
    public void unbindDevice(String tagId)
    {
        TagInfo tagInfo = tagInfoMapper.selectById(tagId);
        tagInfoMapper.unbindDevice(tagId);
        String deviceSbId = deviceInfoMapper.selectSbId(tagInfo.getParentId());
        removeTagInfo(deviceSbId, tagInfo.getSbId());
        sendOptTagMsg(deviceSbId,tagInfo,TAG_OPT_DEL);
    }

    /**
     * 判断指定读写器下是否存在标签
     */
    @Override
    public boolean hasChildOfParentId(String parentId)
    {
        return tagInfoMapper.hasChildOfParentId(parentId) != 0;
    }

    /**
     * 获取标签属性历史数据
     *
     * @param logQueryBo 物模型单属性历史查询搜索实体类
     */
    @Override
    public List<TagData> getPropertyHistory(DevicePropertyLogQueryBo logQueryBo)
    {
        TagInfo tagInfo = tagInfoMapper.selectById(logQueryBo.getDeviceId());
        if (tagInfo == null) {
            return null;
        }
        logQueryBo.setProductKey(tagInfo.getProductKey());
        List<TagData> history = tagDataMapper.findDevicePropertyHistory(logQueryBo);
        CollectionUtil.reverse(history);
        return history;

        //return devicePropertyData.findDevicePropertyHistory(logQueryBo);
    }

    /**
     * 查询所有标签下拉框
     *
     * @return 标签下拉框
     */
    @Override
    public List<SelectEntity> selectList()
    {
        TagInfo tagInfo = new TagInfo();
        return tagInfoMapper.selectOptions(tagInfo);
    }

    @Override
    public List<SelectEntity> selectList(String deviceId)
    {
        return tagInfoMapper.selectOptions1(deviceId);
    }


    @Override
    public List<ThingModelVo.Property> getThingModelOfId(String tagId)
    {
        String productKey = tagInfoMapper.selectProductKey(tagId);
        return thingModelService.findByProductKey(productKey).getModel().getProperties();
    }

    @Override
    public TagInfo selectTagInfo(String readerId, String tagId)
    {
        return tagInfoMapper.selectBySbId(tagId);
    }
}
